package com.jiezuo.common.exception;

import com.jiezuo.common.enums.ResultEnums;
import com.jiezuo.common.util.ResultUtil;
import com.jiezuo.common.vo.Result;
import com.mysql.jdbc.MysqlDataTruncation;
import com.mysql.jdbc.MysqlErrorNumbers;
import com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException;
import lombok.extern.slf4j.Slf4j;
import org.apache.catalina.connector.ClientAbortException;
import org.springframework.dao.DataIntegrityViolationException;
import org.springframework.jdbc.BadSqlGrammarException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;

import javax.servlet.http.HttpServletRequest;

/**
 * @description 全局异常处理
 * @author 庞留杰
 * @date 2020/7/23 16:50
 * @version V1.0
 **/
//@RestControllerAdvice = @ControllerAdvice + @ResponseBody
@RestControllerAdvice
@Slf4j
public class GlobalExceptionHandler {

    @ExceptionHandler(value = Exception.class)
    protected Result exp1(HttpServletRequest request, Exception e) {
        log.error(ResultEnums.INTERNAL_SERVER_ERROR.getReasonPhraseCN(), e);
        return ResultUtil.error(ResultEnums.INTERNAL_SERVER_ERROR.getCode(), ResultEnums.INTERNAL_SERVER_ERROR.getReasonPhraseCN(), e.getMessage());
    }

    @ExceptionHandler(value = BusinessRuntimeException.class)
    protected Result exp2(HttpServletRequest request, BusinessRuntimeException e) {
        log.error(e.getMsg(), e);
        return ResultUtil.error(ResultEnums.FAIL.getCode(), e.getMsg());
    }


    @ExceptionHandler(value = ClientAbortException.class)
    protected Result exp4(HttpServletRequest request, ClientAbortException e) {
        log.error(e.getMessage(), e);
        //return new ResultUtil<>().error(ResultEnums.REQUEST_TIMED_OUT.getCode(), ResultEnums.REQUEST_TIMED_OUT.getReasonPhraseCN());
        return new ResultUtil<>().error("3001", "客户端异常终止，请刷新页面重试");
    }

    @ExceptionHandler(value = DataIntegrityViolationException.class)
    protected Result exp5(HttpServletRequest request, DataIntegrityViolationException e) {
        /**
         *  MYSQL异常:
         *    字符串太长: Cause: com.mysql.jdbc.MysqlDataTruncation: Data truncation: Data too long for column '字段名' at row 1
         *    整数太长: com.mysql.jdbc.MysqlDataTruncation: Data truncation: Out of range value for column '字段名' at row 1
         */
        if (e.getCause() instanceof MysqlDataTruncation && (
                ((MysqlDataTruncation) e.getCause()).getErrorCode() == MysqlErrorNumbers.ER_DATA_TOO_LONG ||
                        ((MysqlDataTruncation) e.getCause()).getErrorCode() == MysqlErrorNumbers.ER_WARN_DATA_OUT_OF_RANGE
        )) {
            log.error(ResultEnums.CONTENT_OUT_OF_LIMIT.getReasonPhraseCN() + "\n\t" + e);
            return new ResultUtil<>().error(ResultEnums.CONTENT_OUT_OF_LIMIT.getCode(), ResultEnums.CONTENT_OUT_OF_LIMIT.getReasonPhraseCN());
        } else {
            return this.exp1(request, e);
        }
    }

    @ExceptionHandler(value = BadSqlGrammarException.class)
    protected Result exp6(HttpServletRequest request, BadSqlGrammarException e) {
        /**
         *  MYSQL异常: 数据库字段缺失
         */
        if (e.getCause() instanceof MySQLSyntaxErrorException && (
                ((MySQLSyntaxErrorException) e.getCause()).getErrorCode() == MysqlErrorNumbers.ER_BAD_FIELD_ERROR
        )) {
            log.error(ResultEnums.DATABASE_FIELD_MISSING.getReasonPhraseCN() + "\n\t" + e);
            return new ResultUtil<>().error(ResultEnums.DATABASE_FIELD_MISSING.getCode(), ResultEnums.DATABASE_FIELD_MISSING.getReasonPhraseCN());
        } else {
            return this.exp1(request, e);
        }
    }

    @ExceptionHandler(value = NullPointerException.class)
    protected Result exp8(NullPointerException e) {
        log.error(e.getMessage(), e);
        return new ResultUtil<>().error(ResultEnums.NULL_POINTER_EXCEPTION.getCode(), ResultEnums.NULL_POINTER_EXCEPTION.getReasonPhraseCN());
    }

}
